#include "list.h"

void list_create(list *l, int blocksize) {
    l->size = blocksize;
    l->count = 0;
    pthread_mutex_init(&l->mutex, NULL);
    l->head = NULL;
}

void list_append(list *l, void *data) {
    node *tmp, *newnode;
    pthread_mutex_lock(&l->mutex);
    newnode = (node *)safe_malloc(l->size);
    newnode->pre = NULL;
    newnode->block = data;
    newnode->next = NULL;
    l->count++;
    tmp = l->head;
    if (tmp == NULL) {
        tmp = newnode;
    } else {
        while (tmp->next != NULL)
            tmp = tmp->next;
        tmp->next = newnode;
        newnode->pre = tmp;
    }
    pthread_mutex_unlock(&l->mutex);
}

int list_remove(list *l, void *data) {
    node *tmp;
    int i;
    pthread_mutex_lock(&l->mutex);
    tmp = l->head;
    if (tmp == NULL) {
        pthread_mutex_unlock(&l->mutex);
        return -1;
    }
    for (i=0; i<l->count; i++) {
        if (tmp->block == data) {
            l->count--;
            if (tmp->pre == NULL) {
                tmp->next->pre = NULL;
                l->head = tmp->next;
            } else {
                tmp->pre->next = tmp->next;
                tmp->next->pre = tmp->pre;
            }
            free(tmp->block);
            free(tmp);
            pthread_mutex_unlock(&l->mutex);
            return 0;
        }
    }
    pthread_mutex_unlock(&l->mutex);
    return -1;
}

void *list_search(list *l, void *v, search_func search) {
    int i;
    node *tmp = l->head;
    pthread_mutex_lock(&l->mutex);
    for(i=0; i<l->count; i++) {
        if(search(tmp->block, v)) {
            pthread_mutex_unlock(&l->mutex);
            return tmp->block;
        }
    }
    pthread_mutex_unlock(&l->mutex);
    return NULL;
}
    
void my_sort(node *base, comp_func comp) {
    node *tmp1;
    node *tmp2;
    tmp1=base; 
    if (tmp1->next == NULL)
        return;
    for (; tmp1->next->next!=NULL; tmp1=tmp1->next) {
        for (tmp2=tmp1; tmp2->next!=NULL; tmp2=tmp2->next) {
            if ((*comp)(tmp2->block, tmp2->next->block) > 0) {
                void *tmp_block;
                tmp_block = tmp2->block;
                tmp2->block = tmp2->next->block;
                tmp2->next->block = tmp_block;
            }
        }
    }
}
    
void list_sort(list *l, comp_func comp) {
    pthread_mutex_lock(&l->mutex);
    if (l->count == 0)
        return;
    my_sort(l->head, comp);
    pthread_mutex_unlock(&l->mutex);
}

void list_cleanup(list *l) {
    node *tmp;
    pthread_mutex_lock(&l->mutex);
    if (l->count > 0) {
        for (tmp=l->head; tmp->next!=NULL; tmp=tmp->next) {
            free(tmp->block);
        }
        tmp = tmp->pre;
        for (;tmp->pre!=NULL; tmp=tmp->pre) {
            free(tmp->next);
            tmp->next = NULL;
        }
        free(l->head);
        l->head = NULL;
    }
    pthread_mutex_unlock(&l->mutex);
    pthread_mutex_destroy(&l->mutex);
}
    
            

            

